#include "vector.h"

#include <iostream>
#include <cmath>
#include <cstdlib>

namespace Splatit {

Vector::Vector(void) : x(0.0), y(0.0) , z(0.0) 
{ }

Vector::Vector(const double _x, const double _y,const double _z) : x(_x), y(_y), z(_z) 
{ }

Vector::Vector(const Vector& _vector) : x(_vector.x) , y(_vector.y) , z(_vector.z) { }

Vector::~Vector(void) { }

double Vector::dot_product(const Vector& _vector) const {
	return x*_vector.x+ y*_vector.y+ z*_vector.z;
}

Vector Vector::cross_product(const Vector& _vector) const {
	
	return Vector(y*_vector.z - z*_vector.y, z*_vector.x - x*_vector.z,x*_vector.y - y*_vector.x);
}

Vector Vector::scalar_product(const double _value) const {
	return Vector(x*_value,y*_value,z*_value);
}

Vector Vector::normalize(void) const{
	Vector normalized(*this);
	double mod = normalized.dot_product(normalized);
	if(mod != 0.0) { 
		normalized = normalized.scalar_product(1.0/sqrt(mod));
		
	}
	return normalized;
}

Vector Vector::sub_vect(const Vector& _vector) const {
	return Vector(this->x-_vector.x,
			this->y-_vector.y,
			this->z-_vector.z);
}

double Vector::length(void) const {
	return sqrt(this->dot_product(*this));
}

double Vector::distance(const Vector& _vector) const {
	return sqrt((x - _vector.x)*(x - _vector.x) + (y - _vector.y)*(y - _vector.y) + (z - _vector.z)*(z - _vector.z));
}

void Vector::set(const double _x,const double _y,const double _z) { 
	x = _x;
	y = _y;
	z = _z;
}

Vector& Vector::operator=(const Vector& _vector) {
	if(this != &_vector) {
		x = _vector.x;
		y = _vector.y;
		z = _vector.z;
	}
	return *this;
}

double Vector::operator*(const Vector& _vector) const {
    return this->dot_product(_vector);
}

const Vector Vector::operator*(const double _value) const {
    return this->scalar_product(_value);
}

const Vector Vector::operator+(const Vector& _vector) const {
    return Vector(x + _vector.x,y + _vector.y,z + _vector.z);
}

double Vector::operator[](const int& _index) const {
	switch(_index) {
		case 1: return x;
		case 2: return y;
		case 3: return z;
		default: exit(1);
	}
}

const Vector Vector::operator-(void) const {
	return Vector(-x,-y,-z);
}

const Vector Vector::operator-(const Vector& _vector) const {
	return sub_vect(_vector);
}
}
